package org.celery.modules.statics.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import org.celery.modules.shop.entity.Shop;
import org.celery.modules.shop.service.IShopService;
import org.celery.modules.statics.service.IDataViewService;
import org.celery.modules.ticket.entity.CustomTicket;
import org.celery.modules.ticket.service.ICustomTicketService;
import org.celery.modules.ticket.vo.CustomTicketVO;
import org.celery.modules.ticket.wrapper.CustomTicketWrapper;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.utils.Func;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@AllArgsConstructor
@Service
public class DataViewServiceImpl implements IDataViewService {

    private final ICustomTicketService customTicketService;
    private final IShopService shopService;

    @Override
    public List<Map<String, Object>> topList(String shopName, LocalDateTime startTime, LocalDateTime endTime, BladeUser user) {
        QueryWrapper<CustomTicket> queryWrapper = new QueryWrapper<>();
        if (Func.isNotEmpty(startTime) && Func.isNotEmpty(endTime)) {
            queryWrapper.lambda().between(CustomTicket::getDate, startTime, endTime);
        }

        if (Func.isNotEmpty(shopName)) {
            List<Shop> shopList = shopService.list(Wrappers.<Shop>lambdaQuery().like(Shop::getResourceOwner, shopName));
            if (Func.isEmpty(shopList)) {
                return new ArrayList<>();
            }
            List<Long> shopIdList = shopList.stream().map(Shop::getId).collect(Collectors.toList());
            queryWrapper.lambda().in(CustomTicket::getShopId, shopIdList);
        }

        if(!user.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID) || (!user.getRoleName().contains("administrator") && !user.getRoleName().contains("s_admin") && !user.getRoleName().contains("caiwu") && !user.getRoleName().contains("fake_boss"))) {
            List<Shop> shopList = shopService.authList(user);
            if (Func.isEmpty(shopList)) {
                return new ArrayList<>();
            }

            List<Long> shopIdList = shopList.stream().map(Shop::getId).collect(Collectors.toList());
            queryWrapper.lambda().in(CustomTicket::getShopId, shopIdList);
        }

        List<CustomTicket> ticketList = customTicketService.list(queryWrapper);
        if (Func.isEmpty(ticketList)) {
            return new ArrayList<>();
        }

        List<Long> shopIdList = ticketList.stream().map(CustomTicket::getShopId).distinct().collect(Collectors.toList());
        List<Shop> shopList = shopService.list(Wrappers.<Shop>lambdaQuery().in(Shop::getId, shopIdList));

        List<Map<String, Object>> list = new ArrayList<>();
        for (Shop shop: shopList) {
            Map<String, Object> data = new HashMap<>();
            data.put("name", shop.getResourceOwner());
            data.put("shopInfo", shopService.shopUserInfo(shop.getId()));

            BigDecimal amount = new BigDecimal(0);
            BigDecimal cost = new BigDecimal(0);
            BigDecimal profit = new BigDecimal(0);
            int ticketCount = 0;
            for (CustomTicket ticket: ticketList) {
                if (ticket.getShopId().equals(shop.getId())) {
                    amount = amount.add(ticket.getSalePrice());
                    cost = cost.add(ticket.getPurchasePrice());
                    profit = profit.add(ticket.getProfit());
                    ticketCount += 1;
                }
            }

            data.put("amount", amount);
            data.put("cost", cost);
            data.put("profit", profit);
            data.put("ticketCount", ticketCount);
            list.add(data);
        }

        list.sort((o1, o2) -> {
            BigDecimal one = (BigDecimal) o1.get("profit");
            BigDecimal two = (BigDecimal) o2.get("profit");
            return two.compareTo(one);
        });

        return list;
    }

    @Override
    public List<Map<String, Object>> lastTicketList(String shopName, LocalDateTime startTime, LocalDateTime endTime, BladeUser user) {
        QueryWrapper<CustomTicket> queryWrapper = new QueryWrapper<>();
        if (Func.isNotEmpty(startTime) && Func.isNotEmpty(endTime)) {
            queryWrapper.lambda().between(CustomTicket::getDate, startTime, endTime);
        }
        if (Func.isNotEmpty(shopName)) {
            List<Shop> shopList = shopService.list(Wrappers.<Shop>lambdaQuery().like(Shop::getResourceOwner, shopName));
            if (Func.isEmpty(shopList)) {
                return new ArrayList<>();
            }
            List<Long> shopIdList = shopList.stream().map(Shop::getId).collect(Collectors.toList());
            queryWrapper.lambda().in(CustomTicket::getShopId, shopIdList);
        }
        if(!user.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID) || (!user.getRoleName().contains("administrator") && !user.getRoleName().contains("s_admin") && !user.getRoleName().contains("caiwu") && !user.getRoleName().contains("fake_boss"))) {
            List<Shop> shopList = shopService.authList(user);
            if (Func.isEmpty(shopList)) {
                return new ArrayList<>();
            }

            List<Long> shopIdList = shopList.stream().map(Shop::getId).collect(Collectors.toList());
            queryWrapper.lambda().in(CustomTicket::getShopId, shopIdList);
        }
        queryWrapper.lambda().orderByDesc(CustomTicket::getDate).orderByDesc(CustomTicket::getCreateTime);
        List<CustomTicketVO> ticketList = CustomTicketWrapper.build().listVO(customTicketService.list(queryWrapper));
        if (Func.isEmpty(ticketList)) {
            return new ArrayList<>();
        }

        List<Map<String, Object>> list = new ArrayList<>();
        for (CustomTicketVO ticket: ticketList) {
            Map<String, Object> data = new HashMap<>();
            data.put("name", ticket.getShopName());
            data.put("id", ticket.getId());
            data.put("shopInfo", ticket.getShopInfo());
            data.put("amount", ticket.getSalePrice());
            data.put("cost", ticket.getPurchasePrice());
            data.put("profit", ticket.getProfit());
            data.put("datetime", ticket.getDate());
            list.add(data);
        }
        return list;
    }
}
